package com.surfilter.massdata.spark.util;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.TreeMap;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.surfilter.massdata.spark.model.DnsStatConsts;
import com.surfilter.massdata.spark.model.OracleConsts;
import com.surfilter.massdata.spark.model.StructIP;

/**
 * @author lhfcws/zicun
 * @since 14-2-17.
 */
public class IPDatabase implements Serializable{
	private static final long serialVersionUID = 1L;
	
	private static final Log log = LogFactory.getLog(IPDatabase.class);
	private static final String SQL_SELECT_ALL_IP_REGIONS = "select * from %s";
	private static IPDatabase _db = null;
	public final TreeMap<Long, Pair<Long, StructIP>> ipExtensionMap = new TreeMap<Long, Pair<Long, StructIP>>();
	
	/**
	 * 将数据库中全部的IP段表读入内存
	 */
	private IPDatabase() {
		ResultSet rs = null;
		String sql = String.format(SQL_SELECT_ALL_IP_REGIONS, "BR2002");
		Statement stmt = null;
		Connection conn = null;
		try {
			conn = JdbcUtil.getConnection();
			stmt = conn.createStatement();
			rs = stmt.executeQuery(sql);
            int i =0;
			while (rs.next()) {
				StructIP structIP = resultToStruIP(rs);
				if (structIP == null) {
					continue;
				}
                i++;
				long beginIPValue = structIP.getBeginIPValue();
				long endIPValue = structIP.getEndIPValue();
				if (ipExtensionMap.containsKey(beginIPValue)) {
					// 判断数据库中的IP段是否有交叉
					if (ipExtensionMap.get(beginIPValue).first >= endIPValue)
						continue;
				}
				synchronized (ipExtensionMap) {
					ipExtensionMap.put(beginIPValue, new Pair<Long, StructIP>(endIPValue, structIP));
				}
			}
            log.info("IPDB size is " + i);
        } catch (Exception e) {
			log.error("Failed to load ip region information from database" , e);
		} finally {
			JdbcUtil.close(rs, stmt, conn);
		}
	}

	public static IPDatabase getInstance() {
		if (_db == null)
			_db = new IPDatabase();
		return _db;
	}

	public StructIP get(String ip) {
		try {
			long value = DNSParser.ip2Long(ip);

			Pair<Long, StructIP> pair = ipExtensionMap.get(ipExtensionMap.floorKey(value));
			if (pair.first - value < 0)
				return null;
			StructIP struct = pair.second;
			StructIP retVal = new StructIP(struct.getBeginIPValue(), struct.getEndIPValue(),struct.getFields());
			retVal.set(DnsStatConsts.IPExField.IP, ip);
			return retVal;
		} catch (NullPointerException ignore) {
			return null;
		} catch (Exception e) {
			log.warn("Failed querying ip from IP database. IP is " + ip);
			return null;
		}
	}

	private StructIP resultToStruIP(ResultSet result) {
		long beginIPValue;
		long endIPValue;
		StructIP structIP = null;
		try {
			beginIPValue = result.getLong(OracleConsts.FIELD_BENGIN_IP_VALUE);
			endIPValue = result.getLong(OracleConsts.FIELD_END_IP_VALUE);
			structIP = new StructIP(beginIPValue, endIPValue);
			String value = result.getString(OracleConsts.FIELD_BEGIN_IP);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.BEGIN_IP, value);

			value = result.getString(OracleConsts.FIELD_END_IP);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.END_IP, value);

			value = result.getString(OracleConsts.FIELD_ISP_ID);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.ISP_ID, value);

			value = result.getString(OracleConsts.FIELD_IP_TYPE);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.IP_TYPE, value);

			value = result.getString(OracleConsts.FIELD_OPERATORS_ID);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.OPERATORS_ID, value);

			value = result.getString(OracleConsts.FIELD_OPERATORS_NAME);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.OPERATORS_NAME, value);

			value = result.getString(OracleConsts.FIELD_ISP_NAME);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.ISP_NAME, value);

			value = result.getString(OracleConsts.FIELD_ISP_JYXKZBH);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.ISP_JYXKZBH, value);

			value = result.getString(OracleConsts.FIELD_PROVINCE);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.PROVINCE, value);

			value = result.getString(OracleConsts.FIELD_CITY);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.CITY, value);

			value = result.getString(OracleConsts.FIELD_COUNTY);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.COUNTY, value);

			value = result.getString(OracleConsts.FIELD_ADDR);

			value = result.getString(OracleConsts.FIELD_HOUSE_CODE);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.HOUSE_CODE, value);

			value = result.getString(OracleConsts.FIELD_HOUSE_NAME);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.HOUSE_NAME, value);
			
			value = result.getString(OracleConsts.FIELD_USING_UNIT_TYPE);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.USING_UNIT_TYPE, value);
			
			//暂时屏蔽，勿删
			/*value = result.getString(OracleConsts.FIELD_OPERATORS_JYXKZBH);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.OPERATORS_JYXKZBH, value);

			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.ADDR, value);

			value = result.getString(OracleConsts.FIELD_IP_USED_TYPE);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.IP_USED_TYPE, value);

			value = result.getString(OracleConsts.FIELD_BANDWIDTH);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.BANDWIDTH, value);

			value = result.getString(OracleConsts.FIELD_USING_UNIT_NAME);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.USING_UNIT_NAME, value);

			value = result.getString(OracleConsts.FIELD_USING_UNIT_LINKMAN);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.USING_UNIT_LINKMAN, value);

			value = result.getString(OracleConsts.FIELD_USING_UNIT_TEL);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.USING_UNIT_TEL, value);

			value = result.getString(OracleConsts.FIELD_USING_UNIT_INDUSTRY_TYPE);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.USING_UNIT_INDUSTRY_TYPE, value);

			value = result.getString(OracleConsts.FIELD_REMARK);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.REMARK, value);

			value = result.getString(OracleConsts.FIELD_SOURCE_UNIT);
			if (StringUtils.isEmpty(value))
				value = DnsStatConsts.NA_STR;
			structIP.set(DnsStatConsts.IPExField.SOURCE_UNIT, value);*/
		} catch (Exception e) {
			if(log.isErrorEnabled()){
				log.error(e.getMessage(),e);
			}
		}
		return structIP;
	}
}

